import { Callout, Tabs } from 'nextra/components';
import { Widget } from '@/components/demo/widget.tsx';
import LinkBadge from '@/components/ui/link-badge/link-badge.tsx';
import LinkBadgeGroup from '@/components/ui/link-badge/link-badge-group.tsx';

# Tappable

An area that responds to touch.

<LinkBadgeGroup>
    <LinkBadge label="API Reference" href="https://pub.dev/documentation/forui/latest/forui.foundation/FTappable-class.html"/>
</LinkBadgeGroup>

<Callout type="info">
  This widget is typically used to create other high-level widgets, e.g., [button](../form/button). You should prefer
  those high-level widgets unless you're creating a custom widget.
</Callout>

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='tappable' query={{}} height={300}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart copy
    FTappable(
      builder:
          (context, data, child) => Container(
            decoration: BoxDecoration(
              color:
                  data.contains(WidgetState.hovered) ? context.theme.colors.secondary : context.theme.colors.background,
              borderRadius: BorderRadius.circular(8),
              border: Border.all(color: context.theme.colors.border),
            ),
            padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12),
            child: child!,
          ),
      child: const Text('Tappable'),
      onPress: () {},
    );
    ```
  </Tabs.Tab>
</Tabs>

## Usage

### `FTappable(...)`

```dart copy
const FTappable(
  style: FTappableStyle(),
  semanticsLabel: 'Label',
  excludeSemantics: false,
  selected: false,
  autofocus: false,
  focusNode: FocusNode(),
  onFocusChange: (focused) {},
  onHoverChange: (hovered) {},
  onStateChange: (delta) {},
  behavior: HitTestBehavior.translucent,
  onPress: () {},
  onLongPress: () {},
  onSecondaryPress: () {},
  onSecondaryLongPress: () {},
  shortcuts: { SingleActivator(LogicalKeyboardKey.enter): ActivateIntent() },
  actions: { ActivateIntent: CallbackAction<ActivateIntent>(onInvoke: (_) {}) },
  builder: (context, state, child) => child!,
  child: const Text('Tappable'),
);
```

### `FTappable.static(...)`

A variant of `FTappable` without any animation. This is similar to using `FTappableMotion.none`.

```dart copy
FTappable.static(
  style: FTappableStyle(),
  semanticsLabel: 'Label',
  excludeSemantics: false,
  selected: false,
  autofocus: false,
  focusNode: FocusNode(),
  onFocusChange: (focused) {},
  onHoverChange: (hovered) {},
  onStateChange: (delta) {},
  behavior: HitTestBehavior.translucent,
  onPress: () {},
  onLongPress: () {},
  onSecondaryPress: () {},
  onSecondaryLongPress: () {},
  shortcuts: { SingleActivator(LogicalKeyboardKey.enter): ActivateIntent() },
  actions: { ActivateIntent: CallbackAction<ActivateIntent>(onInvoke: (_) {}) },
  builder: (context, state, child) => child!,
  child: const Text('Tappable'),
);
```

## Custom Bounce Animation

```dart copy
// Default animation.
FTappableMotion(bounceTween: FTappableMotion.defaultBounceTween);

// No animation.
FTappableMotion(bounceTween: FTappableMotion.noBounceTween);

// Custom tween.
FTappableMotion(bounceTween: Tween(begin: 1.0, end: 0.97));
```
